package com.ican.dao.product;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;

import com.ican.common.SystemConstants;
import com.ican.common.hibernate.HibernateDao;
import com.ican.common.hibernate.Page;
import com.ican.domain.product.Product;

@Repository("productDao")
public class ProductDao extends HibernateDao<Product, Integer> {

    public List<Product> findProductByName(String name){
        return this.find("from Product where name = ?", name);
    }
    public List<Product> findProductByCode(String code){
        return this.find("from Product where code = ?", code);
    }
    public List<Product> findProductByNameAndCode(String name, String code){
        return this.find("from Product where name = ? and code = ?", new Object[]{name, code});
    }
    public Product findProductByNameAndCodeAndLang(String name, String code, Integer langId){
        return this.findUnique("from Product where name = ? and code = ? and langId = ?", new Object[]{name, code, langId});
    }
    public Product findProductByUrlFlagAndLang(String urlFlag, Integer langId){
        return this.findUnique("from Product where urlFlag = ? and langId = ?", new Object[]{urlFlag, langId});
    }
    
    public Page<Product> findAllProduct(Page<Product> page, Product product){
        List<String> params = new ArrayList<String>();
        if(product != null){
            if(product.getCategoryId() != null){
                params.add("categoryId = " + product.getCategoryId());
            }
            if(product.getName() != null && product.getName().length() > 0){
                params.add("name like '%" + product.getName() + "%'");
            }
            if(product.getLangId() != null){
                params.add("langId = " + product.getLangId());
            }
            if(product.getSynStatus() != null && product.getSynStatus() >= 0){
                params.add("synStatus = " + product.getSynStatus());
            }
            if(product.getNcStatus() != null && product.getNcStatus() >= 0){
                params.add("ncStatus = " + product.getNcStatus());
            }
        }
        StringBuffer sb = new StringBuffer("from Product");
        if(params.size() > 0){
            sb.append(" where ");
            for(int i = 0; i < params.size(); i++){
                if(i != 0){
                    sb.append(" and ");
                }
                sb.append(params.get(i));
            }
        }
        sb.append(" order by createTime desc ");
        return this.findPage(page, sb.toString());
    }
    public Product findAllProductToSynById(Integer id){
        StringBuffer sb = new StringBuffer("from Product where id = ");
        sb.append(id);
        sb.append(" and synStatus != " + SystemConstants.ENTITY_DATE_SYN_STATUS_RUN);
        return this.findUnique(sb.toString());
    }
    @SuppressWarnings("unchecked")
    public List<Integer> findAllProductIdsToSynByCateId(Integer cateId){
        StringBuffer sb = new StringBuffer("select id from Product where categoryId = ");
        sb.append(cateId);
        sb.append(" and synStatus != ");
        sb.append(SystemConstants.ENTITY_DATE_SYN_STATUS_RUN);
        sb.append(" and ncStatus > ");
        sb.append(SystemConstants.NC_STATUS_RUN);
        return this.createQuery(sb.toString()).list();
    }
    public void updateProductSynStatus(Integer proId, Integer synStatus){
        StringBuffer sb = new StringBuffer("update Product set synTime = :p_syn_time, synStatus = :p_syn_status where id = :p_id");
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("p_syn_time", new Date());
        params.put("p_syn_status", synStatus);
        params.put("p_id", proId);
        this.batchExecute(sb.toString(), params);
    }
    public void updateProductSynProId(String code, Integer synProductId){
        StringBuffer sb = new StringBuffer("update Product set synProductId = ");
        sb.append(synProductId);
        sb.append(" where code = '");
        sb.append(code);
        sb.append("'");
        this.batchExecute(sb.toString());
    }
    
    public void updateProductNcStatus(Integer proId, Integer ncStatus){
        StringBuffer sb = new StringBuffer("update Product set ncTime = :p_nc_time, ncStatus = :p_nc_status where id = :p_id");
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("p_nc_time", new Date());
        params.put("p_nc_status", ncStatus);
        params.put("p_id", proId);
        this.batchExecute(sb.toString(), params);
    }
    
    public void updateProduct(Product product){
        StringBuffer sb = new StringBuffer("update Product set modifyTime = :p_time");
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("p_time", new Date());
        if(product.getName() != null){
            sb.append(", name = :p_name");
            params.put("p_name", product.getName());
        }
        if(product.getCode() != null){
            sb.append(", code = :p_code");
            params.put("p_code", product.getCode());
        }
        if(product.getPrice() != null){
            sb.append(", price = :p_price");
            params.put("p_price", product.getPrice());
        }
        if(product.getPriceUnit() != null){
            sb.append(", priceUnit = :p_price_unit");
            params.put("p_price_unit", product.getPriceUnit());
        }
        if(product.getWeight() != null){
            sb.append(", weight = :p_weight");
            params.put("p_weight", product.getWeight());
        }
        if(product.getWeightUnit() != null){
            sb.append(", weightUnit = :p_weight_unit");
            params.put("p_weight_unit", product.getWeightUnit());
        }
        if(product.getDescription() != null){
            sb.append(", description = :p_description");
            params.put("p_description", product.getDescription());
        }
        if(product.getNcTime() != null){
            sb.append(", ncTime = :p_nc_time");
            params.put("p_nc_time", product.getNcTime());
        }
        if(product.getNcStatus() != null){
            sb.append(", ncStatus = :p_nc_status");
            params.put("p_nc_status", product.getNcStatus());
        }
        if(product.getSynTime() != null){
            sb.append(", synTime = :p_syn_time");
            params.put("p_syn_time", product.getSynTime());
        }
        if(product.getSynStatus() != null){
            sb.append(", synStatus = :p_syn_status");
            params.put("p_syn_status", product.getSynStatus());
        }
        if(product.getSynProductId() != null){
            sb.append(", synProductId = :p_syn_product_id");
            params.put("p_syn_product_id", product.getSynProductId());
        }
        sb.append(" where id = :p_id");
        params.put("p_id", product.getId());
        this.batchExecute(sb.toString(), params);
    }

    @SuppressWarnings("unchecked")
    public List<Integer> getAllProductIdForNcByCategory(Integer categoryId, Integer ncStatus){
        StringBuffer hql = new StringBuffer("select id from Product where categoryId = ");
        hql.append(categoryId);
        if(ncStatus != null){
            if(ncStatus == SystemConstants.NC_STATUS_NO){
                hql.append(" and ncStatus = ");
                hql.append(SystemConstants.NC_STATUS_NO);
            }else{
                hql.append(" and (ncStatus = ");
                hql.append(SystemConstants.NC_STATUS_NO);
                hql.append(" or ncStatus = ");
                hql.append(ncStatus);
                hql.append(")");
            }
        }
        return this.createQuery(hql.toString()).list();
    }
    
}
